package com.lcf.feign.config;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.lcf.base.exception.ExceptionEnum;
import com.lcf.base.exception.SysException;
import com.lcf.base.model.R;
import feign.FeignException;
import feign.Response;
import feign.codec.Decoder;

import java.io.IOException;
import java.lang.reflect.Type;
import java.util.Objects;

/**
 * 描述：openfeign业务异常拦截
 *
 * @author lcf
 * @since 2025/3/4 19:19
 */
public class FeignDecoder implements Decoder {
    private final ObjectMapper objectMapper;

    public FeignDecoder(ObjectMapper objectMapper) {
        this.objectMapper = objectMapper;
    }

    /**
     * 考虑4种情况
     * 1、服务提供方返回null，则返回null
     * 2、服务提供方报错了，被全局异常捕获了，则抛出异常
     * 3、服务提供方正常返回实体，则返回实体
     * 4、服务提供方正常返回R，则返回R
     */
    @Override
    public Object decode(Response response, Type type) throws IOException, FeignException {
        // 读取响应体
        byte[] bodyData = response.body().asInputStream().readAllBytes();
        String body = new String(bodyData);

        // 判断是否是空字符串
        if (body.trim().isEmpty()) {
            // 如果目标类型是 String，返回空字符串
            if (type == String.class) {
                return "";
            }
            // 否则返回 null
            return null;
        }

        // 解析为 JsonNode
        JsonNode jsonNode = objectMapper.readTree(body);
        // 判断是否是 R
        if (jsonNode.has("code") && jsonNode.has("msg") && jsonNode.has("data")) {
            // 解析为 R
            R<?> r = objectMapper.readValue(body, R.class);

            // 检查 code 字段
            if (!Objects.equals(r.getCode(), ExceptionEnum.SUCCESS.getCode())) {
                throw new SysException(r.getCode(), r.getMsg());
            }

            return r;
        }

        // 直接解析为目标类型
        return objectMapper.readValue(body, objectMapper.constructType(type));
    }
}
